#include "syntax_tree.h"
#include "semantic_analyzer.h"
#include "main_container.h"
#include "errors_warnings.h"
extern MainContainer * CompilerData;



// Gr_MethodStatement__GotoStatement
// Gr_GotoStatement__goto_NAME_spSemiCol
SemanticsMethodStatementGoto * SemanticAnalyzer::ReadMSGoto(SyntaxTreeNode * msGotoNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadMSGoto");
#endif
	SemanticsMethodStatementGoto *smsg;
	smsg = new SemanticsMethodStatementGoto();

	if(msGotoNode->Production == Gr_MethodStatement__GotoStatement)
	{
		SyntaxTreeNode * GotoStatementNode = msGotoNode->Nodes->GetData(0);
		if(GotoStatementNode->Production == Gr_GotoStatement__goto_NAME_spSemiCol)
		{
			SyntaxTreeNode * nameNode = GotoStatementNode->Nodes->GetData(1);
			smsg->Name = GatherFromNameNode(nameNode);
		}	
	}

	else
	{
		// ERROR has been found
		// MAKE LOGICAL RECOVERING
	}
	return smsg;
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("ReadMSGoto");
#endif
}

// Gr_ReturnStatement__return_Expression_spSemiCol
// Gr_ReturnStatement__return_spSemiCol
SemanticsMethodStatementReturn * SemanticAnalyzer::ReadMSReturn(SyntaxTreeNode * msReturnNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadMSReturn");
#endif
	SemanticsMethodStatementReturn *smsr;
	smsr = new SemanticsMethodStatementReturn();

	if(msReturnNode->Production == Gr_ReturnStatement__return_Expression_spSemiCol)
	{
		SyntaxTreeNode * expressionNode = msReturnNode->Nodes->GetData(1);
		smsr->Expression = GatherFromExpression( expressionNode );
	} 
	else if(msReturnNode->Production == Gr_ReturnStatement__return_spSemiCol)
	{
	}
	else
	{
		// ERROR has been found
		// MAKE LOGICAL RECOVERING
	}

	return smsr;
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("ReadMSReturn");
#endif
}

// <start_assignment> ~ NAME = <expression>
SemanticsMethodStartAssignment * SemanticAnalyzer::ReadMSStartAssignment(SyntaxTreeNode * msStartAssignmentNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadMSStartAssignment");
#endif
	SemanticsMethodStartAssignment *smsa;
	smsa = new SemanticsMethodStartAssignment();

	// Gr_StartAssignment__NAME_opAssign_Expression
	if(msStartAssignmentNode->Production == Gr_StartAssignment__NAME_opAssign_Expression)
	{
		// <start_assignment> ~ NAME = <expression>
		SyntaxTreeNode * nameNode = msStartAssignmentNode->Nodes->GetData(0);
		SyntaxTreeNode * expressionNode = msStartAssignmentNode->Nodes->GetData(2);
		smsa->Name = GatherFromNameNode(nameNode);
		smsa->Expression = GatherFromExpression(expressionNode);
	} 
	else
	{
		// ERROR has been found
		// MAKE LOGICAL RECOVERING
	}

	return smsa;
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("ReadMSStartAssignment");
#endif
}
// Gr_MethodStatement__StartStatement
// Gr_StartStatement__start_Name_spLPar_Parameters_spRPar_spSemiCol
// Gr_StartStatement__start_Name_spLPar_Parameters_spRPar_with_StartAssignments_spSemiCol
SemanticsMethodStatementStart * SemanticAnalyzer::ReadMSStart(SyntaxTreeNode * msStartNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadMSStart");
#endif
	SemanticsMethodStatementStart *smss;
	smss = new SemanticsMethodStatementStart();

    // Gr_MethodStatement__StartStatement
	if(msStartNode->Production == Gr_MethodStatement__StartStatement)
	{
		SyntaxTreeNode * startStatementNode = msStartNode->Nodes->GetData(0);
		if(startStatementNode->Production == Gr_StartStatement__start_Name_spLPar_Arguments_spRPar_spSemiCol)
		{
			// Gr_StartStatement__start_Name_spLPar_Parameters_spRPar_spSemiCol
			SyntaxTreeNode * nameNode = startStatementNode->Nodes->GetData(1);
			SyntaxTreeNode * argumentsNode = startStatementNode->Nodes->GetData(3);

			//Gr_Arguments__Expression_ArgumentsAdd
			SyntaxTreeNode * expressionNode = argumentsNode->Nodes->GetData(0);
			SyntaxTreeNode * argumentsAddNode = argumentsNode->Nodes->GetData(1);
			smss->Parameters->Add(GatherFromExpression(expressionNode));
			// <arguments_add> ~ <argument_comma_add> <arguments_add> 
			for(int i=0; i< argumentsAddNode->Nodes->GetCount(); i++)
			{
				SyntaxTreeNode * argumentsCommaAddNode = argumentsAddNode->Nodes->GetData(i);
				// <argument_comma_add> ~ , <expression>
				SyntaxTreeNode * expressionNodeI = argumentsCommaAddNode->Nodes->GetData(1);
				smss->Parameters->Add(GatherFromExpression(expressionNodeI));
			}

			smss->Name=GatherFromNameNode(nameNode);
		}
		else if(startStatementNode->Production == Gr_StartStatement__start_Name_spLPar_Arguments_spRPar_with_StartAssignments_spSemiCol)
		{
			// Gr_StartStatement__start_Name_spLPar_Parameters_spRPar_with_StartAssignments_spSemiCol
			SyntaxTreeNode * nameNode = startStatementNode->Nodes->GetData(1);
			smss->Name=GatherFromNameNode(nameNode);

			SyntaxTreeNode * argumentsNode = startStatementNode->Nodes->GetData(3);

			//Gr_Arguments__Expression_ArgumentsAdd
			SyntaxTreeNode * expressionNode = argumentsNode->Nodes->GetData(0);
			SyntaxTreeNode * argumentsAddNode = argumentsNode->Nodes->GetData(1);
			smss->Parameters->Add(GatherFromExpression(expressionNode));
			// <arguments_add> ~ <argument_comma_add> <arguments_add> 
			for(int i=0; i< argumentsAddNode->Nodes->GetCount(); i++)
			{
				SyntaxTreeNode * argumentsCommaAddNode = argumentsAddNode->Nodes->GetData(i);
				// <argument_comma_add> ~ , <expression>
				SyntaxTreeNode * expressionNodeI = argumentsCommaAddNode->Nodes->GetData(1);
				smss->Parameters->Add(GatherFromExpression(expressionNodeI));
			}

 			smss->HasWithPart=true;

			SyntaxTreeNode * startAssigementsNode = startStatementNode->Nodes->GetData(6);
			// <start_assignments> ~ <start_assignment> <start_assignment_add>
			SyntaxTreeNode * startAssigementNode = startAssigementsNode->Nodes->GetData(0);
			smss->WithAssignments->Add(ReadMSStartAssignment(startAssigementNode));
			SyntaxTreeNode * startAssigementAddNode = startAssigementsNode->Nodes->GetData(1);

			// <start_assignment_add> ~ <start_assignment_comma_add> <start_assignment_add>
			for (int i=0; i< startAssigementAddNode->Nodes->GetCount(); i++)
			{
				// <start_assignment_comma_add> ~ , <start_assignment>
				SyntaxTreeNode * startAssigementCommaAddNode = startAssigementAddNode->Nodes->GetData(i);
                SyntaxTreeNode * startAssigementNodeI = startAssigementCommaAddNode->Nodes->GetData(i);
				smss->WithAssignments->Add(ReadMSStartAssignment(startAssigementNodeI));
			}			
		}
	}
	else
	{
		// ERROR has been found
		// MAKE LOGICAL RECOVERING
	}
	return smss;
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("ReadMSStart");
#endif
}

// Gr_MethodStatement__StopStatement
// Gr_StopStatement__stop_Name_spSemiCol
SemanticsMethodStatementStop * SemanticAnalyzer::ReadMSStop(SyntaxTreeNode * msStopNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadMSStop");
#endif
	SemanticsMethodStatementStop *smss;
	smss = new SemanticsMethodStatementStop();

	if(msStopNode->Production == Gr_MethodStatement__StopStatement)
	{
		// Gr_StopStatement__stop_Name_spSemiCol
		SyntaxTreeNode * stopStatementNode = msStopNode->Nodes->GetData(0);
		if (stopStatementNode->Production == Gr_StopStatement__stop_Name_spSemiCol)
		{
			SyntaxTreeNode * nameNode = stopStatementNode->Nodes->GetData(1);
			smss->Name = GatherFromNameNode(nameNode);
		}
	}
	else
	{
		// ERROR has been found
		// MAKE LOGICAL RECOVERING
	}

	return smss;
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("ReadMSStop");
#endif
}

// Gr_MethodStatement__AssignmentDerivation
// Gr_AssignmentDerivation__derivation_VariableValue_opAssign_Expression_spSemiCol
SemanticsMethodStatementDerivationAssignment * SemanticAnalyzer::ReadMSDerivationAssignment(SyntaxTreeNode * msDerivationAssignmentNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadMSDerivationAssignment");
#endif
	SemanticsMethodStatementDerivationAssignment *smsda;
	smsda = new SemanticsMethodStatementDerivationAssignment();

	if(msDerivationAssignmentNode->Production == Gr_MethodStatement__AssignmentDerivation)
	{
		SyntaxTreeNode * assignmentDerivationNode = msDerivationAssignmentNode->Nodes->GetData(0);
		if (assignmentDerivationNode->Production == Gr_AssignmentDerivation__derivation_VariableValue_opAssign_Expression_spSemiCol)
		{
			SyntaxTreeNode * variableValueNode = assignmentDerivationNode->Nodes->GetData(1);
			SyntaxTreeNode * expressionNode = assignmentDerivationNode->Nodes->GetData(3);
			smsda->RValue = GatherFromExpression(expressionNode);
//TODO			smsda->LValue 
		}
	}
	else
	{
		// ERROR has been found
		// MAKE LOGICAL RECOVERING
	}

	return smsda;
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("ReadMSDerivationAssignment");
#endif
}


